package com.ftg.learn.bus.service.impl;

import com.ftg.learn.bus.VO.MenuVo;
import com.ftg.learn.bus.entity.LoginUser;
import com.ftg.learn.bus.entity.Menu;
import com.ftg.learn.bus.lnterceptor.LoginInterceptor;
import com.ftg.learn.bus.mapper.MenuMapper;
import com.ftg.learn.bus.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author lalala
 * @since 2022-03-07
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Resource
    MenuMapper menuMapper;

    /**
     * 根据菜单id修改菜单名
     * @param id
     * @param title
     * @return
     */
    @Override
    public boolean updateForName(Long id, String title) {
        return this.baseMapper.updateForName(id,title);
    }
    /**
     * 查询当前用户所有权限菜单
     * @param uid 用户id
     * @return 当前用户权限
     */
    @Override
    public List<MenuVo> showMenuForUserId(Long uid) {
        return menuMapper.showMenuForUserId(uid);
    }

    /**
     * 查询当前角色下的所有权限
     * @param rid 角色id
     * @return 角色权限
     */
    @Override
    public List<MenuVo> showMenuForRoleId(Long rid) {
        return menuMapper.showMenuForRoleId(rid);
    }

    /**
     * 默认的全局最大的结点 父id
     */
    private final long DEFAULT_PARENT_ID = -1;

    /**
     * 获得当前某个的全部角色
     * @param uid 当前用户的编号
     * @return
     */
    @Override
    public String logedByPermssion(Long uid) {

        List<MenuVo> list = menuMapper.showMenuForUserId(uid);
        //转换...把当前方法的给的list 转换成一颗树
        try {
            System.out.println("=============================1111111111111111111");
            return this.parsePermissionWithTree(list, DEFAULT_PARENT_ID).toString();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "[]";
    }



    /**
     * 转换功能
     * @param list  全部角色
     * @param begin 最上级的角色 parentid
     */
    private JSONArray parsePermissionWithTree(List<MenuVo> list, Long begin) throws JSONException {
        JSONArray rearr = new JSONArray();
        if(Objects.isNull(list) && list.size() == 0){
            return rearr;
        }
        for (int i = 0; i < list.size(); i++) {
            MenuVo vo = list.get(i);
            if(!Objects.isNull(vo) && vo.getParentId().equals(begin)){
                JSONObject reobj = new JSONObject();
                reobj.put("title",vo.getTitle());
                reobj.put("href",vo.getHref());
                reobj.put("target","_self");
                reobj.put("child",parsePermissionWithTree(list, vo.getMid()));
                rearr.put(reobj);
            }
        }
        return rearr;
    }
    /**
     *
     * @param rid 用户id
     * @param mids 菜单数组
     * @return 成功/失败
     */
    @Transactional(rollbackFor = SQLException.class)
    @Override
    public boolean saveOrUpdateMenusByRid(Long rid, List<Long> mids) {
        menuMapper.deleteMenuByRid(rid);
        for (Long l : mids){
            menuMapper.saveOrUpdateMenusByRid(rid,l);
        }
        return true;
    }


    @Override
    public JSONObject findMenuTree(Long rid) {
        JSONObject json = new JSONObject();
        //生成全部数据
        List<Menu> oldAll =this.baseMapper.selectList(null);
        JSONArray list = null;
        List<MenuVo> myself = this.menuMapper.showMenuForRoleId(rid);
        System.out.println(">>>>>>>>>>>>>>>>>"+oldAll.toString());
        System.out.println("<<<<<<<<<<<>>>>>>"+myself.toString());
        List<Long> ids = new ArrayList<>();
        for(MenuVo my : myself){
            ids.add(my.getMid());
        }
        try {
            list = this.toplevel(oldAll,Long.parseLong("-1"),ids);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        //生成我有的数据
        try {
            json.put("allinfo",list);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 生成当前数据的最外层，为了完成与前台格式的相对应
     *     递归   ：  当某一个方法  对这个方法进行了调用的时候，我们把这种调用方式叫递归
     * @param list       数据库里面查询出来的数据格式
     * @param startid    最顶元素的parent_id
     * @return
     * @throws JSONException
     *  parentid = -1   id = 1  parentid = -1
     *  object o;
     *  id = 1
     *  title 系统 管理
     *  firstlv.ut(o)
     *  o.put("children",)
     */
    private JSONArray toplevel(List<Menu> list, Long startid,List<Long> plist) throws JSONException {
        JSONArray firstlv = new JSONArray();
        for (Menu p : list) {
            if(p.getParentId().equals(startid)){
                JSONObject obj = new JSONObject();
                // 生成相当于前面页面的对象格式
                obj.put("id",p.getMid());  // 编号
                obj.put("title",p.getTitle());  //名称
                obj.put("checked",plist.contains(p.getMid()) && p.getIsleaf()==1);
                firstlv.put(obj);
                obj.put("children",toplevel(list,p.getMid(),plist)); //子元素


            }
        }
        return firstlv;
    }

    /**
     * 分级查询当前用户权限菜单
     * @return 当前用户权限
     * from 项目经理 康加修
     */
    @Override
    public List<MenuVo> queryMenu() {
        List<MenuVo> target = new ArrayList<>();
        LoginUser loginUser = LoginInterceptor.loginUserThreadLocal.get();
        Long id = loginUser.getId();
        // 查询出的数据
        List<MenuVo> list = this.showMenuForUserId(id);
        createTree(target,list,Long.parseLong("-1"));
        return target;
    }


    /**
     * 是不是应该把 pid 当做一个条件
     *      判断 pid 是否有子项
     *         list 里面有元素的parentid = pid 有
     *         。。。parentid所在这个元素添到pid childlist
     *         递归 pid
     *         return ;
     * @param pid 数据主键
     * @param target 目标
     * @param data 源数据
     * @return 无返回值
     * * from 项目经理 康加修
     * pid -1
     */
    public void createTree(List<MenuVo> target,List<MenuVo> data,Long pid) {
        if(findSon(data,pid)){
            data.forEach(x->{
                if(x.getParentId().equals(pid) ){
                    //一定要把x扔进去
                    MenuVo parent = findParent(data,x);
                    if(parent == null){
                        target.add(x);// 把-1添加到的target  x.getPid();
                    }else{
                        parent.getChildList().add(x);
                    }
//                    data.remove(x);// 有可能会有问题
                    createTree(target,data,x.getMid());
                }
            });
        }
    }

    /**
     * 找子项
     * @param data 源数据
     * @param pid  主键 --- pid与parentId相同
     * @return 找当前权限的子权限
     * * from 项目经理 康加修
     */
    public boolean findSon(List<MenuVo> data,Long pid){
        return data.stream().anyMatch(x -> x.getParentId().equals(pid) );
    }

    /**
     * 是不是存sno在 target里面是否有父亲,修改成递归 childList == null
     * @param data 父亲的所有元素
     * @param son    子元素
     * @return 找菜单的父级菜单
     * * from 项目经理 康加修
     */
    public MenuVo findParent(List<MenuVo> data,MenuVo son){
        for (MenuVo permissionVo : data) {
            if(permissionVo.getMid().equals(son.getParentId())){
                return permissionVo;
            } else{
                findParent(permissionVo.getChildList(),son);
            }
        }
        return null;
    }
}
